import 'dart:io';

import 'package:flutter_template/utils/utils.dart';
import 'package:sqflite/sqflite.dart';
import 'package:sqflite_common_ffi/sqflite_ffi.dart';

import 'package:flutter_template/config/consts.dart';
import './entities/basic_entity.dart';
import "./entities/diary.dart";

class DB {
  DB._privateConstructor();

  static final DB _instance = DB._privateConstructor();

  static DB get instance {
    return _instance;
  }

  Database? db;

  bool dbOpened() {
    if (db == null) {
      return false;
    }

    return db!.isOpen;
  }

  /// 创建 DB 连接并创建数据库表
  Future<bool> openDB() async {
    if (dbOpened()) {
      return true;
    }

    try {
      if (Platform.isWindows || Platform.isLinux) {
        sqfliteFfiInit();
      }

      db = await openDatabase(Consts.dbname, version: Consts.dbVersion);
      await _createTable();
      return true;
    } catch (e) {
      logger(e);
      return false;
    }
  }

  Future<void> _createTable() async {
    List<String> tableNames = [DiaryTable.tableName];
    for (var index = 0; index < tableNames.length; index++) {
      bool created = await _tableCreated(tableNames[index]);
      if (!created) {
        logger("创建数据库表 \"${DiaryTable.tableName}\"");
        await db!.execute(DiaryTable.createTableSql);
      }
    }
  }

  Future<bool> _tableCreated(String tableName) async {
    String sql =
        "SELECT * FROM sqlite_master WHERE type='table' AND name='$tableName'";
    List<Map<String, Object?>> list = await db!.rawQuery(sql);
    return list.isNotEmpty;
  }

  /// 关闭数据库表
  Future closeDb() async {
    if (dbOpened()) {
      await db!.close();
    }
  }

  /// 插入数据
  Future<T?> insert<T extends BasicEntity>(String tableName, T data) async {
    bool opened = await openDB();
    if (!opened) return null;

    data.id = await db!.insert(tableName, data.toMap());
    return data;
  }

  /// 更新数据
  Future<T?> update<T extends BasicEntity>(String tableName, T data) async {
    bool opened = await openDB();
    if (!opened) return null;

    await db!.update(
      tableName,
      data.toMap(),
      where: '_id=?',
      whereArgs: [data.id],
    );

    return data;
  }

  /// 删除数据
  Future<bool> delete(String tableName, int id) async {
    bool opened = await openDB();
    if (!opened) return false;

    await db!.delete(tableName, where: '_id=?', whereArgs: [id]);

    return true;
  }
}
